{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "basics.ipynb",
      "version": "0.3.2",
      "provenance": [],
      "private_outputs": true,
      "collapsed_sections": [],
      "toc_visible": true
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.6.5"
    },
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "iPpI7RaYoZuE"
      },
      "source": [
        "##### Copyright 2018 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "form",
        "colab_type": "code",
        "id": "hro2InpHobKk",
        "colab": {}
      },
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "U9i2Dsh-ziXr"
      },
      "source": [
        "# テンソルと演算"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Hndw-YcxoOJK"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/customization/basics\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />View on TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/ja/tutorials/customization/basics.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/ja/tutorials/customization/basics.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />View source on GitHub</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "RSywPQ2n736s"
      },
      "source": [
        "Note: これらのドキュメントは私たちTensorFlowコミュニティが翻訳したものです。コミュニティによる 翻訳は**ベストエフォート**であるため、この翻訳が正確であることや[英語の公式ドキュメント](https://www.tensorflow.org/?hl=en)の 最新の状態を反映したものであることを保証することはできません。 この翻訳の品質を向上させるためのご意見をお持ちの方は、GitHubリポジトリ[tensorflow/docs](https://github.com/tensorflow/docs)にプルリクエストをお送りください。 コミュニティによる翻訳やレビューに参加していただける方は、 [docs-ja@tensorflow.org メーリングリスト](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ja)にご連絡ください。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "6sILUVbHoSgH"
      },
      "source": [
        "これは、下記の手法を示す TensorFlow の入門チュートリアルです。\n",
        "\n",
        "* 必要なパッケージのインポート\n",
        "* テンソルの作成と使用\n",
        "* GPUによる高速化の使用\n",
        "* `tf.data.Dataset`のデモ"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "miTaGiqV9RjO",
        "colab": {}
      },
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "\n",
        "!pip install tensorflow-gpu==2.0.0-rc1"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "z1JcS5iBXMRO"
      },
      "source": [
        "## TensorFlowのインポート\n",
        "\n",
        "はじめに、`tensorflow` モジュールをインポートします。TensorFlow 2.0 では、eager execution が既定でオンとなっています。\n",
        "これにより、TensorFlow のフロントエンドがよりインタラクティブになります。詳細は後述します。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "vjBPmYjLdFmk",
        "colab": {}
      },
      "source": [
        "import tensorflow as tf"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "H9UySOPLXdaw"
      },
      "source": [
        "## テンソル\n",
        "\n",
        "テンソルは多次元配列です。NumPy の `ndarray` オブジェクトと同様に、`tf.Tensor` にはデータ型と形状があります。これに加えて、`tf.Tensor` は（ GPU のような）アクセラレータのメモリに置くことができます。TensorFlow には、`tf.Tensor` を使用し生成するたくさんの演算([tf.add](https://www.tensorflow.org/api_docs/python/tf/add), [tf.matmul](https://www.tensorflow.org/api_docs/python/tf/matmul), [tf.linalg.inv](https://www.tensorflow.org/api_docs/python/tf/linalg/inv) など)のライブラリが存在します。これらの演算では、ネイティブな Python データ型が自動変換されます。例を示します。\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "code",
        "colab_type": "code",
        "id": "ngUe237Wt48W",
        "colab": {}
      },
      "source": [
        "print(tf.add(1, 2))\n",
        "print(tf.add([1, 2], [3, 4]))\n",
        "print(tf.square(5))\n",
        "print(tf.reduce_sum([1, 2, 3]))\n",
        "\n",
        "# Operator overloading is also supported\n",
        "print(tf.square(2) + tf.square(3))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "IDY4WsYRhP81"
      },
      "source": [
        "それぞれの`tf.Tensor`には、形状とデータ型があります。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "srYWH1MdJNG7",
        "colab": {}
      },
      "source": [
        "x = tf.matmul([[1]], [[2, 3]])\n",
        "print(x)\n",
        "print(x.shape)\n",
        "print(x.dtype)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "eBPw8e8vrsom"
      },
      "source": [
        "NumPy 配列と `tf.Tensor` の間のもっとも明確な違いは\n",
        "\n",
        "1. テンソルは（ GPU や TPU などの）アクセラレータメモリを使用できる\n",
        "2. テンソルは変更不可"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Dwi1tdW3JBw6"
      },
      "source": [
        "### NumPy互換性\n",
        "\n",
        "TensorFlow の`tf.Tensor`と NumPy の `ndarray` 間の変換は簡単です。\n",
        "\n",
        "* TensorFlow の演算により NumPy の ndarray は自動的にテンソルに変換される\n",
        "* NumPy の演算によりテンソルは自動的に NuｍPy の ndarray に変換される\n",
        "\n",
        "テンソルは `.numpy()` メソッドを使って明示的に NumPy の ndarray に変換されます。NumPy のndarray と `tf.Tensor` はその下敷きとなるメモリ上の表現が、できるかぎり共通化されているので、通常この変換のコストは小さいです。しかし、NumPy 配列はホスト側のメモリに置かれる一方、`tf.Tensor` はGPU のメモリに置かれる可能性もあるため、下層の表現をいつも共通化できるとは限りません。また、変換にはGPU からホスト側メモリへのコピーも関わってきます。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "lCUWzso6mbqR",
        "colab": {}
      },
      "source": [
        "import numpy as np\n",
        "\n",
        "ndarray = np.ones([3, 3])\n",
        "\n",
        "print(\"TensorFlow演算によりnumpy配列は自動的にテンソルに変換される\")\n",
        "tensor = tf.multiply(ndarray, 42)\n",
        "print(tensor)\n",
        "\n",
        "\n",
        "print(\"またNumPy演算によりテンソルは自動的にnumpy配列に変換される\")\n",
        "print(np.add(tensor, 1))\n",
        "\n",
        "print(\".numpy()メソッドによりテンソルは明示的にnumpy配列に変換される\")\n",
        "print(tensor.numpy())"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "PBNP8yTRfu_X"
      },
      "source": [
        "## GPU による高速化\n",
        "\n",
        "TensorFlow の演算の多くは、GPU を計算に使用することで高速化されます。TensorFlow は演算に注釈をつけなくとも、自動的に GPU と CPU のどちらかを選択し、必要であればテンソルを GPU メモリと CPU メモリの間でコピーして実行します。演算で生成されたテンソルは通常演算を実行したデバイスのメモリに置かれます。例を見てみましょう。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "code",
        "colab_type": "code",
        "id": "3Twf_Rw-gQFM",
        "colab": {}
      },
      "source": [
        "x = tf.random.uniform([3, 3])\n",
        "\n",
        "print(\"利用できるGPUはあるか: \"),\n",
        "print(tf.config.experimental.list_physical_devices(\"GPU\"))\n",
        "\n",
        "print(\"テンソルはGPU #0にあるか:  \"),\n",
        "print(x.device.endswith('GPU:0'))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "vpgYzgVXW2Ud"
      },
      "source": [
        "### デバイス名\n",
        "\n",
        "`Tensor.device` プロパティにより、そのテンソルの内容を保持しているデバイスの完全な名前文字列を得ることができます。この名前には、プログラムを実行中のホストのネットワークアドレスや、ホスト上のデバイスについての詳細がエンコードされています。この情報は、TensorFlow プログラムの分散実行に必要なものです。テンソルがホスト上の `N` 番目のGPUにある場合、文字列の最後は `GPU:<N>` となります。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "ZWZQCimzuqyP"
      },
      "source": [
        "### 明示的デバイス配置\n",
        "\n",
        "TensorFlowでいう**配置**は、個々の演算を実行するためにどのようにデバイスにアサイン（配置）されるかを指します。前述のとおり、明示的な示唆がなければ、TensorFlow は演算を実行するデバイスを自動的に決め、必要であればテンソルをそのデバイスにコピーします。しかし、`tf.device` コンテキストマネジャーを使うことで、TensorFlow の演算を特定のデバイスに配置することができます。例を見てみましょう。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "RjkNZTuauy-Q",
        "colab": {}
      },
      "source": [
        "import time\n",
        "\n",
        "def time_matmul(x):\n",
        "  start = time.time()\n",
        "  for loop in range(10):\n",
        "    tf.matmul(x, x)\n",
        "\n",
        "  result = time.time()-start\n",
        "    \n",
        "  print(\"10 loops: {:0.2f}ms\".format(1000*result))\n",
        "\n",
        "# CPUでの実行を強制\n",
        "print(\"On CPU:\")\n",
        "with tf.device(\"CPU:0\"):\n",
        "  x = tf.random.uniform([1000, 1000])\n",
        "  assert x.device.endswith(\"CPU:0\")\n",
        "  time_matmul(x)\n",
        "\n",
        "# GPU #0があればその上での実行を強制\n",
        "if tf.config.experimental.list_physical_devices(\"GPU\"):\n",
        "  print(\"On GPU:\")\n",
        "  with tf.device(\"GPU:0\"): # 2番めのGPUなら GPU:1, 3番目なら GPU:2 など\n",
        "    x = tf.random.uniform([1000, 1000])\n",
        "    assert x.device.endswith(\"GPU:0\")\n",
        "    time_matmul(x)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "o1K4dlhhHtQj"
      },
      "source": [
        "## データセット\n",
        "\n",
        "このセクションでは [`tf.data.Dataset` API](https://www.tensorflow.org/guide/datasets) を使って、モデルにデータを供給するためのパイプラインを構築します。`tf.data.Dataset` APIは、単純で再利用可能な部品をもとに、モデルの訓練あるいは評価ループにデータを供給する高性能で複雑な入力パイプラインを構築するために使われます。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "zI0fmOynH-Ne"
      },
      "source": [
        "### ソース`Dataset`の作成\n",
        "\n",
        "\n",
        "[Dataset.from_tensors](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#from_tensors) や[Dataset.from_tensor_slices](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#from_tensor_slices) といったファクトリー関数または [TextLineDataset](https://www.tensorflow.org/api_docs/python/tf/data/TextLineDataset) あるいは[TFRecordDataset](https://www.tensorflow.org/api_docs/python/tf/data/TFRecordDataset) のようなファイルを読み込むオブジェクトを使って、 **元となる**データセットを作成しましょう。詳しくは、[TensorFlow Dataset guide](https://www.tensorflow.org/guide/datasets#reading_input_data) を参照してください。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "F04fVOHQIBiG",
        "colab": {}
      },
      "source": [
        "ds_tensors = tf.data.Dataset.from_tensor_slices([1, 2, 3, 4, 5, 6])\n",
        "\n",
        "# CSVファイルを作成\n",
        "import tempfile\n",
        "_, filename = tempfile.mkstemp()\n",
        "\n",
        "with open(filename, 'w') as f:\n",
        "  f.write(\"\"\"Line 1\n",
        "Line 2\n",
        "Line 3\n",
        "  \"\"\")\n",
        "\n",
        "ds_file = tf.data.TextLineDataset(filename)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "vbxIhC-5IPdf"
      },
      "source": [
        "### 変換の適用\n",
        "\n",
        "[map](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#map),  [batch](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#batch),  [shuffle](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#shuffle) などの変換関数を使って、データセットレコードに変換を適用します。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "uXSDZWE-ISsd",
        "colab": {}
      },
      "source": [
        "ds_tensors = ds_tensors.map(tf.square).shuffle(2).batch(2)\n",
        "\n",
        "ds_file = ds_file.batch(2)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "A8X1GNfoIZKJ"
      },
      "source": [
        "### イテレート\n",
        "\n",
        "`tf.data.Dataset` オブジェクトは、中のレコードを繰り返し利用するためのイテレーションをサポートします。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "ws-WKRk5Ic6-",
        "colab": {}
      },
      "source": [
        "print('ds_tensors の要素:')\n",
        "for x in ds_tensors:\n",
        "  print(x)\n",
        "\n",
        "print('\\nds_file の要素:')\n",
        "for x in ds_file:\n",
        "  print(x)"
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}
